Arrow keys / Space to navigate

Module 7: Writing Effective Lambda Functions

Developing Serverless Solutions on AWS

Topics

Lambda Runs in Ephemeral Environments

Analogy: Food truck. It parks (INIT), serves customers (INVOKE), and if idle too long, drives away (SHUTDOWN). Next customer = new truck or reuse the parked one.
Concurrency = number of function invocations running at one time Cold Start Create + init environment Warm Reuse Skip init, run handler Handler Runs Your code executes Freeze After idle period

Lambda may create a new "cold" environment or reuse a "warm" one

Lambda Best Practices (Lifecycle)

Pre-heat the oven (INIT) once, then cook many dishes (handler invocations). Don't restart the oven for every order.

Environment Reuse: Initialize Outside Handler

// Declare DynamoDB client OUTSIDE handler - runs once during INIT
const AWS = require("aws-sdk");
var ddbClient = new AWS.DynamoDB();
const tableName = process.env.SAMPLE_TABLE;  // From env vars

exports.putItemHandler = async (event) => {
  // Handler runs every invocation - keep it lean
  const { body, httpMethod, path } = event;
  if (httpMethod !== 'POST') {
    throw new Error(`postMethod only accepts POST`);
  }
  // Use pre-initialized ddbClient...
};
Park your car once (INIT), then make multiple trips inside the building (handler). Don't re-park for every trip.

Environment Reuse: /tmp as Transient Cache

const fs = require('fs');
const s3 = new AWS.S3();

exports.handler = async (event) => {
  let config;
  try {
    // Try loading from /tmp (warm invocation - instant!)
    config = fs.readFileSync('/tmp/config.json');
  } catch (e) {
    // Cold start - download from S3, save to /tmp
    let data = await s3.getObject({Bucket:'mybucket', Key:'config.json'}).promise();
    config = data.Body.toString('utf8');
    fs.writeFileSync('/tmp/config.json', config);
  }
  return config;
};

/tmp provides up to 10GB of ephemeral storage that persists across warm invocations.

Database Connection Pooling with RDS Proxy

Problem: High concurrency exhausts DB connections Env 1 Env 2 Env N Lambda RDS Proxy Connection pooling Single endpoint Amazon RDS Limited connections Pooled
Without proxy: Every Lambda opens its own connection (like every guest bringing their own waiter). With proxy: One shared pool (one team of waiters serves everyone).

Memory and Timeout Configuration

128 MB 1/10 vCPU 1 vCPU (1769MB) 6 vCPU (10GB) 10 GB Use AWS Lambda Power Tuning to find the optimal cost/performance point

Provisioned Concurrency

Valet parking: Your car is already running and warmed up when you arrive. Zero wait. On-demand = finding a spot yourself (cold start possible).

Lambda Layers & Environment Variables

Layers

Environment Variables

Layers = shared pantry (everyone uses the same ingredients). Env vars = labels on boxes (different contents per environment).

Idempotency

The results of processing the same input multiple times should have no additional effect on the outcome.

Must account for:

Use event source unique identifiers:

// SQS event - use messageId as idempotency key
"Records": [{
  "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",  // Unique!
  "body": "Test message.",
  "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3"       // Unique!
}]
Elevator button: Press 5 times, still only 1 elevator comes.

Kiro - AI-Powered Development Environment

AI-powered IDE that helps developers focus on what matters: designing systems, exploring solutions, and making decisions.

PhaseWhat Kiro Does
PlanSpecs-driven development: requirements, design, tasks workflow
CreateWrites code autonomously, generates implementations from specs
Test & SecureRuns builds, validates changes, checks for errors automatically
OperateHooks for automation, MCP integrations, infrastructure management
MaintainSteering files for standards, context-aware refactoring
Kiro = your AI development partner. It reads your codebase, understands your architecture, writes code, runs tests, and deploys - all guided by structured specs or free-form conversation.

Versions and Aliases

$LATEST Version 1 Version 2 Alias: DEV Alias: PROD V1: 90% V2: 10% Canary deployment points to $LATEST Aliases = pointers to versions. Shift traffic for canary/blue-green.

Lambda Error Handling - Two Types

1. Invocation Errors (400/500) Lambda has an issue with the event Throttling prevents new invocations Caller receives error status code 2. Function Errors Function does not complete successfully X-Amz-Function-Error header returned Handling depends on invocation type

Error Handling Differs by Event Source

Source TypeWho Handles ErrorsRetry Behavior
SynchronousCLIENT handles all errorsClient must implement retries
AsynchronousLambda shares handling0-2 retries + retry invoke up to 6 hours. Then: DLQ or OnFailure destination
Polling (SQS)Lambda managesBatch fails = messages become visible again. Partial batch response to report individual failures.
Polling (Streams)Lambda managesBlocks shard until success or expiry. Options: bisect batch, max retries, checkpointing.
Restaurant analogy: Sync = customer waits at counter (they deal with mistakes). Async = order submitted, kitchen retries if burned. Polling = buffet attendant keeps refilling until tray is done.

Error Handling: SQS Queues

SQS Queue Batch of messages Visibility timeout Lambda Process batch Report failures Success: Delete msg Fail: DLQ after N tries

Best practice: Use ReportBatchItemFailures - only failed messages retry, successful ones are deleted. Set max receives on DLQ to limit retries.

Error Handling: Streams (Kinesis/DDB)

Assembly line analogy: Bisect = split the batch to find the defective item. Checkpointing = mark where you stopped so you don't redo finished work. DLQ = rejection bin for investigation.

What's New (2024-2025)

Q1: Where should you initialize your DynamoDB client?

B) Outside handler - Runs during INIT, reused across warm invocations.
A: Creates new client every call (wasteful). C: Adds latency. D: Env vars store strings, not objects.

Q2: Async Lambda fails. Default behavior?

B) 0-2 retries then discard. Use DLQ/destination to capture.
A: Not immediate - retries first. C: That's streams. D: Async returns 202, caller never sees errors.

Q3: What problem does RDS Proxy solve for Lambda?

B) Connection pooling. High Lambda concurrency can exhaust DB connections. Proxy pools them.
A: Provisioned Concurrency solves cold starts. C: TLS does that. D: Memory is configured separately.

Q4: What does BisectBatchOnFunctionError do for streams?

A) Splits batch in half. Recursively bisects until isolating the poison record, then sends to OnFailure destination.
B: That skips good records. C: Data loss. D: Makes problem worse.

Module Summary